home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 19 / Mac Magazin and MacEasy Magazine CD - Issue 19.iso / Online / HttpServerƒ / •Mac_Classes / TThread.cp < prev    next >
Text File  |  1996-01-03  |  8KB  |  278 lines

  1. //    TThread.cp - Macintosh Thread class object
  2. // 
  3. // Apple Macintosh Developer Technical Support
  4. // Written by:  Vinne Moscaritolo
  5. //
  6. //  Copyright (work in progress)  Apple Computer, Inc All rights reserved.
  7. //
  8. // You may incorporate this sample code into your applications without
  9. // restriction, though the sample code has been provided "AS IS" and the
  10. // responsibility for its operation is 100% yours.  However, what you are
  11. // not permitted to do is to redistribute the source as "DSC Sample Code"
  12. // after having made changes. If you're going to re-distribute the source,
  13. // we require that you make it clear in the source that the code was
  14. // descended from Apple Sample Code, but that you've made changes.
  15. // 
  16.  
  17.  
  18. #include "TMacException.h"
  19. #include "TThread.h"
  20.  
  21. #include "TNetworkException.h"
  22. #include <strstream.h>
  23.  
  24. // ===========================================================================
  25. //    Static member variables
  26. // ===========================================================================
  27.  
  28. Boolean                TThread::fgInited     = false;    // is Thread class library inited
  29. ProcessSerialNumber    TThread::fgPSN;                    // application's PSN
  30. ThreadTaskRef        TThread::fgThreadTaskRef;        // thread task ref
  31.  
  32. // ---------------------------------------------------------------------------
  33. //     DoEntry (pascal wrapper function)
  34. // ---------------------------------------------------------------------------
  35. //    Thread manager Callback for thread entry
  36.  
  37. pascal void* TThread::DoEntry(void *arg)
  38. {
  39.     TThread *theThread = (TThread*) arg;
  40.     void* theResult;
  41.         
  42. //    try
  43.     {
  44.         theResult = theThread->Run();
  45.     }
  46.     
  47. //    catch(...)        
  48.     {
  49.     // stop error prop
  50.     } 
  51.  
  52. // Recycle thread
  53.     theThread->Stop(theResult);
  54.  
  55. // cant get here...    
  56.     ThrowMsg("TThread :DoEntry returned from dispose");
  57.     return nil;
  58. }
  59.  
  60. // ---------------------------------------------------------------------------
  61. //     DoTermination (pascal wrapper function)
  62. // ---------------------------------------------------------------------------
  63. //    Thread manager Callback for thread termination
  64.  
  65. pascal void  TThread::DoTermination(ThreadID theID, void *arg)
  66. {
  67.     TThread *theThread = (TThread*) arg;
  68.     
  69.     theThread->fTID = kNoThreadID;
  70.     
  71.     try
  72.     {
  73.         theThread->Done();
  74.     }
  75.     catch(...)
  76.     {        
  77.         // all we want is to stop error propagation
  78.     } 
  79. }
  80.  
  81. // ---------------------------------------------------------------------------
  82. //     DoSwapIn (pascal wrapper function)
  83. // ---------------------------------------------------------------------------
  84. //    Thread manager Callback for thread Swap in
  85.  
  86. pascal void    TThread::DoSwapIn(ThreadID, void *arg)
  87. {
  88.     TThread* theThread = (TThread*) arg;
  89.         
  90.     theThread->fContext.Restore();    
  91. }
  92.  
  93.  
  94. // ---------------------------------------------------------------------------
  95. //     DoSwapOut (pascal wrapper function)
  96. // ---------------------------------------------------------------------------
  97. //    Thread manager Callback for thread Swap Out
  98.  
  99. pascal void    TThread::DoSwapOut(ThreadID, void *arg)
  100. {
  101.     TThread  *theThread = (TThread*) arg;
  102.     
  103.     theThread->fContext.Save();    
  104. }
  105.  
  106. // ---------------------------------------------------------------------------
  107. //     TThread
  108. // ---------------------------------------------------------------------------
  109. //    Default Constructor
  110.  
  111. TThread::TThread()
  112. {
  113. // Check if first time to use thread package
  114.     if (!fgInited) Initialize();
  115.  
  116. // Set state
  117.     fTID =     kNoThreadID;
  118. }
  119.  
  120.  
  121. // ---------------------------------------------------------------------------
  122. //     ~TThread
  123. // ---------------------------------------------------------------------------
  124. //    Destructor
  125.  
  126. TThread::~TThread()
  127. {
  128. // Kill thread if it's running
  129.     Stop(0);
  130.     fTID = kNoThreadID;
  131. }
  132.  
  133. // ---------------------------------------------------------------------------
  134. //     Start
  135. // ---------------------------------------------------------------------------
  136. //     Setup thread for execution
  137.  
  138. void TThread::Start()
  139. {
  140.     OSErr ErrNo;
  141.     
  142.     try    {
  143.  
  144. // Create thread
  145.         ThrowIfOSErr (::NewThread( kCooperativeThread,            // kCooperativeThread,kPreemptiveThread
  146.                                     DoEntry,                      // thread entry proc
  147.                                     this,                        // param to entry proc 
  148.                                     0,                            // Stack space
  149.                                     (kReadyThreadState             // starting state (ready)
  150.                                     | kCreateIfNeeded),            // try to get from pool
  151.                                     (void**) &fResult,            // place to put quit result
  152.                                     &fTID));                    // place to put task ID
  153.  
  154. // set terminator and thread switch procs
  155.         ThrowIfOSErr(::SetThreadSwitcher(fTID, DoSwapIn, this, true));
  156.         ThrowIfOSErr(::SetThreadSwitcher(fTID, DoSwapOut, this, false));
  157.          ThrowIfOSErr(::SetThreadTerminator(fTID, DoTermination, this));
  158.     }
  159.     catch(...){
  160.         if (fTID != kNoThreadID) {
  161.             ::SetThreadTerminator(fTID, nil, nil);
  162.             ::DisposeThread(fTID, nil, true);
  163.             fTID = kNoThreadID;
  164.             }
  165.         throw;
  166.     }
  167.  }
  168.  
  169. // ---------------------------------------------------------------------------
  170. //    Stop
  171. // ---------------------------------------------------------------------------
  172. //     Stop thread execution
  173.  
  174. void TThread::Stop(void * theResult)
  175. {
  176.     
  177.     if(fTID != kNoThreadID){
  178.         ThreadID  ourThread = fTID;
  179.         fTID = kNoThreadID;                                // this might be the last thing this thread does
  180.         ::DisposeThread(ourThread,theResult, true);        // so juggle the Tid
  181.         };
  182. }
  183.  
  184. // ---------------------------------------------------------------------------
  185. //    Sleep
  186. // ---------------------------------------------------------------------------
  187. //    Sleep Thread
  188.  
  189. void TThread::Sleep()
  190. {
  191.     if(fTID != kNoThreadID)
  192.         ThrowIfOSErr(::SetThreadState(fTID,kStoppedThreadState,kCurrentThreadID));
  193. }
  194.  
  195.  
  196. // ---------------------------------------------------------------------------
  197. //    WakeUp
  198. // ---------------------------------------------------------------------------
  199. //    Wake up Thread
  200.  
  201. void TThread::WakeUp()
  202. {
  203.     ThreadState threadState;
  204.     
  205.     if( (fTID != kNoThreadID) 
  206.         && (::GetThreadStateGivenTaskRef(fgThreadTaskRef, fTID,&threadState) != noErr)
  207.         && (threadState == kStoppedThreadState))
  208.             ::SetThreadReadyGivenTaskRef(fgThreadTaskRef, fTID);
  209. }
  210.  
  211.  
  212. // ---------------------------------------------------------------------------
  213. //    Yield
  214. // ---------------------------------------------------------------------------
  215. //    Yield  time to next thread
  216.  
  217. void TThread::Yield()
  218. {
  219.     ::YieldToAnyThread();
  220. }
  221.  
  222.  
  223. // ---------------------------------------------------------------------------
  224. //    Run
  225. // ---------------------------------------------------------------------------
  226. //    default thread Run
  227.  
  228. void* TThread::Run()
  229. {
  230.      while(true) {
  231.          Yield();
  232.          }
  233.      return nil;
  234. }
  235.  
  236. // ---------------------------------------------------------------------------
  237. //    Done
  238. // ---------------------------------------------------------------------------
  239. //    default thread Done
  240.  
  241. void TThread::Done()
  242. {
  243. }
  244.  
  245.  
  246.  
  247. // ---------------------------------------------------------------------------
  248. //     Allocate (static public)
  249. // ---------------------------------------------------------------------------
  250. //    Allocate memory for Thread manager
  251.  
  252. void TThread::Allocate(short numToCreate, Size stackSize)
  253. {
  254.     ThrowIfOSErr(::CreateThreadPool(kCooperativeThread, numToCreate, stackSize));
  255. }
  256.  
  257.  
  258. // ---------------------------------------------------------------------------
  259. //     Initialize 
  260. // ---------------------------------------------------------------------------
  261. //    Will  run when first thread is started
  262.  
  263. void TThread::Initialize()
  264. {
  265. // is the Thread Manager running ?
  266. /*        if (!UEnvironment::HasFeature(env_HasThreadsManager))
  267.         {
  268.             ThrowOSErr_(threadProtocolErr);
  269.         }
  270. */        
  271. // low-level initialisation
  272.     ThrowIfOSErr( ::GetCurrentProcess(&fgPSN));
  273.     ThrowIfOSErr( ::GetThreadCurrentTaskRef(&fgThreadTaskRef));
  274.  
  275.     fgInited = true;
  276. }
  277.  
  278.